package cc.rengu.igas.bsps.core.service.trans;

import cc.rengu.igas.bsps.common.constant.BspsAppParamConstant;
import cc.rengu.igas.bsps.common.dao.*;
import cc.rengu.igas.bsps.common.dao.impl.*;
import cc.rengu.igas.bsps.common.entity.*;
import cc.rengu.igas.bsps.common.enums.*;
import cc.rengu.igas.bsps.core.model.UserSessionInfo;
import cc.rengu.igas.bsps.core.service.base.ManageService;
import cc.rengu.igas.bsps.facade.base.Header;
import cc.rengu.igas.bsps.facade.bean.MchntBindInfoBean;
import cc.rengu.igas.bsps.facade.bean.PrivilegeInfoBean;
import cc.rengu.igas.bsps.facade.request.UserLogInOutRequest;
import cc.rengu.igas.bsps.facade.response.UserLogInOutResponse;
import cc.rengu.igas.share.common.util.SensitiveDataUtil;
import cc.rengu.igas.share.core.model.GroupMchntInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.common.constant.AppConfigConstant;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.common.enums.PinTypeEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.PasswordInfo;
import cc.rengu.oltp.service.realize.SafeKeyBoardService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.SafeKeyBoardServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户登录登出服务
 * Created by 王成 on 2018/6/13.
 *
 * @author zhangxuran (联调修改)
 * @version 1.0
 * @date 2020.06.13
 */
public class UserLogInOutService extends ManageService {

    @Override
    protected Object bizBeforeCust() throws Exception {
        UserLogInOutRequest userLogInOutRequest = new UserLogInOutRequest();
        ConvertUtil.convertOutput(userLogInOutRequest);
        return userLogInOutRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        UserLogInOutRequest userLogInOutRequest = (UserLogInOutRequest) request;
        Header header = userLogInOutRequest.getHeader();
        String instId = header.getInstId();
        String userId = userLogInOutRequest.getUserId();
        String password = userLogInOutRequest.getPassword();
        //操作类型
        String oprType = userLogInOutRequest.getOprType();
        //登录类型
        String loginType = userLogInOutRequest.getLoginType();
        String channelId = userLogInOutRequest.getHeader().getChanlId();
        UserLogInOutResponse userLogInOutResponse = new UserLogInOutResponse();
        String session = userLogInOutRequest.getHeader().getSession();
        if (StringUtil.isEmptyOrNull(loginType) || StringUtil.isEmptyOrNull(oprType) || StringUtil.isEmptyOrNull(instId)) {
            rglog.error("必填性校验失败！");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
        /* 用户登录 */
        if (BspsLogInOutOprEnum.LOGIN.getOprType().equals(userLogInOutRequest.getOprType())) {
            /* 仅在登录时验session，登出时可能存在session超时，单独处理 */
            UserSessionInfo keySessionInfo = JSON.parseObject(RedisUtil.onceGet(header.getSession()), UserSessionInfo.class);
            if (null == keySessionInfo) {
                rglog.error("session超时");
                throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
            }
            UserInfo userInfo = getUserInfoByRequest(userLogInOutRequest, instId, loginType);
            /* 判断用户登录错误次数 */
            if (null != userInfo.getLastLoginDate() && userInfo.getLastLoginDate().equals(DateUtil.getCurrentDate()) && userInfo.getLoginErrorTimes() >= 5) {
                rglog.error("用户连续登陆失败次数超限(5次)!");
                throw new BizException(RespCodeEnum.USER_LOGIN_ERROR_OVERRUN.getRespCode(), RespCodeEnum.USER_LOGIN_ERROR_OVERRUN.getRespDesc());
            }
            BspsMchntBindInfoMapper mchntBindInfoMapper = new BspsMchntBindInfoMapperImpl();
            /* 如果是账户/密码登录校验密码 */
            if (BspsLoginTypeEnum.ACCT_PASSWORD.getLoginType().equals(loginType)) {
                if (StringUtil.isEmptyOrNull(password)) {
                    rglog.error("用户<{}>密码为空或者密码错误！", userId);
                    updateUserLoginErrorTimes(userInfo);
                    throw new BizException(RespCodeEnum.GET_USER_INFO_ERROR.getRespCode(), RespCodeEnum.GET_USER_INFO_ERROR.getRespDesc());
                }
                String passwordVerifyKey = keySessionInfo.getPasswordVerifyKey();
                //校验密码信息
                SafeKeyBoardService safeKeyBoardService = new SafeKeyBoardServiceImpl();
                if (StringUtil.isEmptyOrNull(passwordVerifyKey)) {
                    List<MchntBindInfo> mchntBindlist = mchntBindInfoMapper.selectBspsMchntBindInfoListByUserId(instId, userInfo.getUserId());
                    if ("WECHAT".equals(channelId)) {
                        rglog.info("微信渠道登录");
                        //校验用户登录密码
                        boolean passwordFlag = false;
                        for (MchntBindInfo mchntBindInfo : mchntBindlist) {
                            PasswordInfo passwordInfo = new PasswordInfo(mchntBindInfo.getMchntNo(), PinTypeEnum.MIXED, password);
                            password = safeKeyBoardService.encryptPassword(instId, null, passwordInfo, null);
                            if (userInfo.getLoginPassword().equalsIgnoreCase(password)) {
                                rglog.info("密码校验成功！instId:<{}>,mchntNo:<{}>", instId, mchntBindInfo.getMchntNo());
                                passwordFlag = true;
                                break;
                            }
                        }
                        if (!passwordFlag) {
                            rglog.error("用户<{}>密码为空或者密码错误！", userLogInOutRequest.getUserId());
                            updateUserLoginErrorTimes(userInfo);
                            throw new BizException(RespCodeEnum.GET_USER_INFO_ERROR.getRespCode(), RespCodeEnum.GET_USER_INFO_ERROR.getRespDesc());
                        } else {
                            /* 清空用户登录次数 */
                            if (userInfo.getLoginErrorTimes() != 0) {
                                userInfo.setLoginErrorTimes(0);
                                BspsUserInfoMapper bspsUserInfoMapper = new BspsUserInfoMapperImpl();
                                int iReturnCode = bspsUserInfoMapper.updateBspsUserErrorTimeByPrimaryKey(userInfo);
                                if (0 != iReturnCode) {
                                    rglog.error("更新用户登录次数失败信息失败!");
                                }
                            }
                        }
                    } else if ("PCWEB".equals(channelId)) {
                        rglog.info("PC渠道登录");
                        String randomString = keySessionInfo.getRandomString();
                        keySessionInfo.setRandomString("");
                        RedisUtil.onceSet(header.getSession(), JSONObject.toJSONString(keySessionInfo), BspsAppParamConstant.SESSION_EFFECTIVE_TIME);
                        //校验用户登录密码
                        boolean passwordFlag = false;
                        for (MchntBindInfo mchntBindInfo : mchntBindlist) {
                            String mchntNo = mchntBindInfo.getMchntNo();
//                            String mchntType = mchntBindInfo.getBindMchntType();
//                            if (BspsMchntTypeEnum.AGENT_MCHNT.getMchntType().equals(mchntType)
//                                    || BspsMchntTypeEnum.PLAT_MCHNT.getMchntType().equals(mchntType)
//                                    || BspsMchntTypeEnum.GROUP_MCHNT.getMchntType().equals(mchntType)
//                            ){
//                                mchntNo = mchntNo.substring(2);
//                            }
                            mchntNo = mchntNo.replaceAll("AG", "").replaceAll("PM", "");
                            PasswordInfo passwordInfo = new PasswordInfo(mchntNo, PinTypeEnum.MIXED, password);
                            if (safeKeyBoardService.verifyPassword(instId, null, userInfo.getLoginPassword(), passwordInfo, null)) {
                                rglog.info("密码校验成功！instId:<{}>,mchntNo:<{}>", instId, mchntBindInfo.getMchntNo());
                                passwordFlag = true;
                                break;
                            }
                        }
                        if (!passwordFlag) {
                            rglog.error("用户<{}>密码为空或者密码错误！", userLogInOutRequest.getUserId());
                            updateUserLoginErrorTimes(userInfo);
                            throw new BizException(RespCodeEnum.GET_USER_INFO_ERROR.getRespCode(), RespCodeEnum.GET_USER_INFO_ERROR.getRespDesc());
                        } else {
                            /* 清空用户登录次数 */
                            if (userInfo.getLoginErrorTimes() != 0) {
                                userInfo.setLoginErrorTimes(0);
                                BspsUserInfoMapper bspsUserInfoMapper = new BspsUserInfoMapperImpl();
                                int iReturnCode = bspsUserInfoMapper.updateBspsUserErrorTimeByPrimaryKey(userInfo);
                                if (0 != iReturnCode) {
                                    rglog.error("更新用户登录次数失败信息失败!");
                                }
                            }
                        }
                    }
                } else {
                    if (!passwordVerifyKey.equals(password)) {
                        rglog.error("用户<{}>密码为空或者密码错误！", userLogInOutRequest.getUserId());
                        updateUserLoginErrorTimes(userInfo);
                        throw new BizException(RespCodeEnum.GET_USER_INFO_ERROR.getRespCode(), RespCodeEnum.GET_USER_INFO_ERROR.getRespDesc());
                    } else {
                        /* 清空用户登录次数 */
                        if (userInfo.getLoginErrorTimes() != 0) {
                            userInfo.setLoginErrorTimes(0);
                            BspsUserInfoMapper bspsUserInfoMapper = new BspsUserInfoMapperImpl();
                            int iReturnCode = bspsUserInfoMapper.updateBspsUserErrorTimeByPrimaryKey(userInfo);
                            if (0 != iReturnCode) {
                                rglog.error("更新用户登录次数失败信息失败!");
                            }
                        }
                    }
                    keySessionInfo.setPasswordVerifyKey("");
                }
            }
            keySessionInfo.setUserId(userInfo.getUserId());
            RedisUtil.onceSet(header.getSession(), JSONObject.toJSONString(keySessionInfo), BspsAppParamConstant.SESSION_EFFECTIVE_TIME);
            //生成新的会话id
            String newSessionId = RandomUtil.getUUID();
            UserSessionInfo userSessionInfo = new UserSessionInfo();
            userSessionInfo.setUserId(userInfo.getUserId());
            userSessionInfo.setSignatureKey(keySessionInfo.getSignatureKey());
            userSessionInfo.setSensitiveKey(keySessionInfo.getSensitiveKey());
            RedisUtil.onceSet(newSessionId, JSONObject.toJSONString(userSessionInfo), BspsAppParamConstant.SESSION_EFFECTIVE_TIME);
            header.setSession(newSessionId);
            userLogInOutResponse.setHeader(header);
            if (!StringUtil.isEmptyOrNull(userInfo.getTransPassword())) {
                userLogInOutResponse.setVerifyFlag("Y");
            } else {
                userLogInOutResponse.setVerifyFlag("N");
            }
            userLogInOutResponse.setUserLoginId(userInfo.getUserLoginId());
            userLogInOutResponse.setUserId(userInfo.getUserId());
            userLogInOutResponse.setNickName(userInfo.getNickName());
            userLogInOutResponse.setEmail(userInfo.getEmail());
            if (!StringUtil.isEmptyOrNull(userInfo.getUserImagePath())) {
                userLogInOutResponse.setUserImagePath(Base64.encodeBase64String(userInfo.getUserImagePath().getBytes()));
            }
            userLogInOutResponse.setUserSex(userInfo.getUserSex());
            if (!StringUtil.isEmptyOrNull(userInfo.getMobileNo())) {
                userLogInOutResponse.setPhoneNo(SensitiveDataUtil.desensitization("1", userInfo.getMobileNo()).split("\\|")[0]);
            }

            /* 获取用户绑定信息及对应角色权限 */
            BspsMchntBindInfoMapper bspsMchntBindInfoMapper = new BspsMchntBindInfoMapperImpl();
            List<MchntBindInfo> mchntBindInfoList = bspsMchntBindInfoMapper.selectBspsMchntBindInfoListByUserId(instId, userInfo.getUserId());
            BspsMchntBaseInfoMapper bspsMchntBaseInfoMapper = new BspsMchntBaseInfoMapperImpl();
            List<MchntBindInfoBean> facadeMchntBindInfoBeanList = new ArrayList<>();
            BspsUserRoleInfoMapper bspsUserRoleInfoMapper = new BspsUserRoleInfoMapperImpl();
            BspsAgentInfoMapper bspsAgentInfoMapper = new BspsAgentInfoMapperImpl();
            BspsPlatformMchntInfoMapper bspsPlatformMchntInfoMapper = new BspsPlatformMchntInfoMapperImpl();
            if (!CollectionUtils.isEmpty(mchntBindInfoList)) {
                rglog.info("绑定信息");
                List<MchntBindInfo> mchntBindInfos = mchntBindInfoList.stream().filter(item -> item.getBindMchntType().equals(BspsMchntTypeEnum.GROUP_MCHNT.getMchntType()) || item.getBindMchntType().equals(BspsMchntTypeEnum.AGENT_MCHNT.getMchntType())
                        || item.getBindMchntType().equals(BspsMchntTypeEnum.PLAT_MCHNT.getMchntType())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(mchntBindInfos) && !"PCWEB".equals(channelId)) {
                    rglog.error("商户为代理商、平台商户或者集团商户，在微信端登录");
                    throw new BizException(RespCodeEnum.MCHNT_CHANNEL_REGISTER.getRespCode(), RespCodeEnum.MCHNT_CHANNEL_REGISTER.getRespDesc());
                }
                for (MchntBindInfo mchntBindInfo : mchntBindInfoList) {
                    MchntBindInfoBean facadeMchntBinInfo = new MchntBindInfoBean();
                    BeanUtil.beanCopy(mchntBindInfo, facadeMchntBinInfo);
                    List<UserRoleInfo> userRoleInfoList = bspsUserRoleInfoMapper.selectBspsUserRoleInfoToChannelMenu(instId, mchntBindInfo.getBindUserRole(), channelId);
                    if (!CollectionUtils.isEmpty(userRoleInfoList)) {
                        List<PrivilegeInfoBean> privilegeInfoBeanList = userRoleInfoList.stream().map(this::convertPrivilegeInfo).collect(Collectors.toList());
                        facadeMchntBinInfo.setPrivilegeInfoBeanList(privilegeInfoBeanList);
                    }
                    facadeMchntBinInfo.setMchntType(mchntBindInfo.getBindMchntType());

                    /*退款权限-法人、店长都有权限,白名单的收银员有权限*/
                    if (((BspsUserRoleTypeEnum.MCHNT_ARTIF.getRoleType().equals(mchntBindInfo.getBindUserRole()))
                            || (BspsUserRoleTypeEnum.MCHNT_MANAGER.getRoleType().equals(mchntBindInfo.getBindUserRole())))) {
                        rglog.info("法人、店长登录");
                        //有退款权限
                        facadeMchntBinInfo.setRefundFlag(AppParamConstant.YES);
                    } else {
                        rglog.info("非法人、店长登录");
                        //校验白名单收银员退款权限,null/NO为无权限
                        SysParamService sysParamService = new SysParamServiceImpl();
                        SysParam sysParam = sysParamService.getSysParamInfo(instId, BspsAppParamConstant.BSPS_REFUND_MERCH, mchntBindInfo.getMchntNo());
                        if (null != sysParam && !StringUtil.isEmptyOrNull(sysParam.getParamValue()) && AppParamConstant.YES.equals(sysParam.getParamValue())) {
                            rglog.info("白名单商户");
                            facadeMchntBinInfo.setRefundFlag(AppParamConstant.YES);
                        } else {
                            rglog.info("非白名单商户");
                            facadeMchntBinInfo.setRefundFlag(AppParamConstant.NO);
                        }
                    }

                    if (BspsMchntTypeEnum.AGENT_MCHNT.getMchntType().equals(mchntBindInfo.getBindMchntType())) {
                        AgentInfo agentInfo = bspsAgentInfoMapper.selectBspsAgentInfoByInstIdAndAgentCode(instId, mchntBindInfo.getMchntNo());
                        if (null == agentInfo || !MchntStatusEnum.NORMAL.getStatus().equals(agentInfo.getAgentStatus())) {
                            rglog.info("代理商信息查询异常或状态异常");
                        } else {
                            facadeMchntBinInfo.setMchntName(agentInfo.getAgentName());
                            facadeMchntBindInfoBeanList.add(facadeMchntBinInfo);
                        }
                    } else if (BspsMchntTypeEnum.PLAT_MCHNT.getMchntType().equals(mchntBindInfo.getBindMchntType())) {
                        PlatformMchntInfo platformMchntInfo = bspsPlatformMchntInfoMapper.selectBspsPlatformMchntInfoByInstIdAndMchntNo(instId, mchntBindInfo.getMchntNo());
                        if (null == platformMchntInfo || !MchntStatusEnum.NORMAL.getStatus().equals(platformMchntInfo.getPlatMchntStatus())) {
                            rglog.error("平台商户信息查询异常或状态异常");
                        } else {
                            facadeMchntBinInfo.setMchntName(platformMchntInfo.getPlatMchntName());
                            facadeMchntBindInfoBeanList.add(facadeMchntBinInfo);
                        }
                    } else if (BspsMchntTypeEnum.GROUP_MCHNT.getMchntType().equals(mchntBindInfo.getBindMchntType())) {
                        MchntService mchntService = new MchntServiceImpl();
                        GroupMchntInfo groupMchntInfo = mchntService.getGroupMchntInfo(instId, mchntBindInfo.getMchntNo());
                        if (null == groupMchntInfo || !MchntStatusEnum.NORMAL.getStatus().equals(groupMchntInfo.getGroupMchntStatus())) {
                            rglog.error("集团商户信息查询异常或状态异常");
                        } else {
                            facadeMchntBinInfo.setMchntName(groupMchntInfo.getGroupMchntName());
                            facadeMchntBindInfoBeanList.add(facadeMchntBinInfo);
                        }
                    } else {
                        MchntBaseInfo mchntBaseInfo = bspsMchntBaseInfoMapper.selectBspsMchntBaseInfoByPrimaryKey(instId, mchntBindInfo.getMchntNo());
                        if (null == mchntBaseInfo || !MchntStatusEnum.NORMAL.getStatus().equals(mchntBaseInfo.getMchntStatus())) {
                            rglog.error("商户信息查询异常或商户状态异常");
                        } else {
                            facadeMchntBinInfo.setMchntName(mchntBaseInfo.getMchntName());
                            facadeMchntBinInfo.setCashWithdrawalFlag(mchntBaseInfo.getCashWithdrawalFlag());
                            facadeMchntBindInfoBeanList.add(facadeMchntBinInfo);
                        }
                    }
                }

            }
            if (CollectionUtils.isEmpty(mchntBindInfoList) || CollectionUtils.isEmpty(facadeMchntBindInfoBeanList)) {
                rglog.info("用户<{}>还未绑定任何商户!", userLogInOutRequest.getUserId());
                if (!AppParamConstant.DEFAULT_ENV.equals(AppParamConstant.APPLICATION_ENV)) {
                    /* 演示环境不进行控制 */
                    if (!"OPENID".equals(userInfo.getOpenId())) {
                        rglog.info("拓展经理用户查询");
                        ManagerInfo managerInfo = null;
                        BspsManagerInfoMapper bspsManagerInfoMapper = new BspsManagerInfoMapperImpl();
                        if ("APP".equals(userLogInOutRequest.getHeader().getChanlId())){
                            managerInfo = bspsManagerInfoMapper.selectBspsManagerInfoById(instId,userLogInOutRequest.getUserId());
                        }else {
                            managerInfo = bspsManagerInfoMapper.selectBspsManagerInfoByOpenId(instId, userInfo.getOpenId());
                        }
                        if (null != managerInfo) {
                            rglog.info("用户已认证拓展经理，无权操作商户菜单");
                            throw new BizException(RespCodeEnum.MANAGER_VERIFY_ERROR.getRespCode(), RespCodeEnum.MANAGER_VERIFY_ERROR.getRespDesc());
                        }
                    }
                }
                rglog.info("同步更新用户信息，不是拓展经理也不是商户，状态修改为解绑");
                userInfo.setLastOprId(userInfo.getUserId());
                userInfo.setUserStatus(UserStatusEnum.CANCEL.getStatus());
                userInfo.setLastUpdateTime(DateUtil.getCurrentDateTime(BspsAppParamConstant.yyyy_MM_dd_HHmmssSSS));

                /* 开启数据库事务 */
                XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
                String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.OLTP_POOL_NAME);
                String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
                if (null != corporation && !corporation.isEmpty()) {
                    String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
                    dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.OLTP_POOL_NAME);
                }
                DbsUtil dbsUtil = new DbsUtil(dbPoolName);
                dbsUtil.dbsBeginTransaction();

                BspsUserInfoMapper bspsUserInfoMapper = new BspsUserInfoMapperImpl();
                int iReturnCode = bspsUserInfoMapper.updateBspsUserInfoByPrimaryKey(userInfo);
                if (0 != iReturnCode && BspsAppParamConstant.NODATA_CODE != iReturnCode) {
                    dbsUtil.dbsEndTransaction(false);
                    rglog.error("同步更新商户用户状态失败");
                    throw new BizException(RespCodeEnum.GET_USER_BIND_INFO_ERROR.getRespCode(), RespCodeEnum.GET_USER_BIND_INFO_ERROR.getRespDesc());
                }
                iReturnCode = bspsMchntBindInfoMapper.updateBspsMchntBindInfoStatusByUserId(instId, userInfo.getUserId());
                if (0 != iReturnCode && BspsAppParamConstant.NODATA_CODE != iReturnCode) {
                    dbsUtil.dbsEndTransaction(false);
                    rglog.error("同步更新商户绑定状态失败");
                    throw new BizException(RespCodeEnum.GET_USER_BIND_INFO_ERROR.getRespCode(), RespCodeEnum.GET_USER_BIND_INFO_ERROR.getRespDesc());
                }
                dbsUtil.dbsEndTransaction(true);

                throw new BizException(RespCodeEnum.GET_USER_INFO_ERROR.getRespCode(), RespCodeEnum.GET_USER_INFO_ERROR.getRespDesc());
            }
            userLogInOutResponse.setMchntBindInfoBeanList(facadeMchntBindInfoBeanList);
            registerUserLoginInfo(userLogInOutRequest, userInfo.getUserId(), userInfo, session);

            /* 用户登出 */
        } else if (BspsLogInOutOprEnum.LOGOUT.getOprType().equals(userLogInOutRequest.getOprType())) {
            if (StringUtil.isEmptyOrNull(userId)) {
                rglog.error("userId为空，必填校验失败");
                throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
            }
            String sessionId = header.getSession();
            if (StringUtils.isEmpty(sessionId)) {
                /* 未上送sessionID时，可能为前端超时后的登出操作，此时不做处理，直接返回 */
                rglog.info("sessionId为空", userLogInOutRequest.getUserId());
            } else {
                UserSessionInfo keySessionInfo = JSON.parseObject(RedisUtil.onceGet(sessionId), UserSessionInfo.class);
                /* 仅在session未超时的情况下，校验用户是否合法，并更新用户登录表 */
                if (null != keySessionInfo) {
                    /* 仅在session未超时的情况下，校验用户ID是否合法 */
                    if (!userId.equals(keySessionInfo.getUserId())) {
                        rglog.error("userId校验失败");
                        throw new BizException(RespCodeEnum.USER_NO_AUTHORITY.getRespCode(), RespCodeEnum.USER_NO_AUTHORITY.getRespDesc());
                    }
                    /* 更新用户登录表 */
                    updateUserLoginInfoByLogout(userLogInOutRequest);
                    /* 清除用户信息缓存 */
                    String sessionKey = userLogInOutRequest.getHeader().getSession();
                    RedisUtil.onceDel(sessionKey);
                }
            }
        } else {
            rglog.error("传入参数用户登录登出操作类型异常！instId:<{}>,oprType:<{}>", instId, oprType);
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        /* 拼装响应结果 */
        BizResponse<UserLogInOutResponse> bizResponse = new BizResponse<>();
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(userLogInOutResponse);
        return bizResponse;
    }

    private PrivilegeInfoBean convertPrivilegeInfo(UserRoleInfo userRoleInfo) {
        PrivilegeInfoBean privilegeInfoBean = new PrivilegeInfoBean();
        BeanUtil.beanCopy(userRoleInfo, privilegeInfoBean);
        return privilegeInfoBean;
    }

    private UserInfo getUserInfoByRequest(UserLogInOutRequest userLogInOutRequest, String instId, String loginType) throws Exception {
        //通过手机银行登录操作交易在T00BS064
        BspsUserInfoMapper bspsUserInfoMapper = new BspsUserInfoMapperImpl();
        UserInfo userInfo;
        if (BspsLoginTypeEnum.OPEN_ID.getLoginType().equals(loginType)) {
            userInfo = bspsUserInfoMapper.selectBspsUserInfoByOpenId(instId, userLogInOutRequest.getOpenId());
        } else if (BspsLoginTypeEnum.ACCT_PASSWORD.getLoginType().equals(loginType)) {
            userInfo = bspsUserInfoMapper.selectBspsUserInfoByUserLoginId(instId, userLogInOutRequest.getUserId());
        } else {
            rglog.error("传入参数用户登录操作类型异常！instId:<{}>,loginType:<{}>", instId, loginType);
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (null == userInfo) {
            rglog.error("用户<{}>信息不存在!", userLogInOutRequest.getUserId(), loginType);
            throw new BizException(RespCodeEnum.GET_USER_INFO_ERROR.getRespCode(), RespCodeEnum.GET_USER_INFO_ERROR.getRespDesc());
        }

        return userInfo;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        UserLogInOutResponse userLogInOutResponse = (UserLogInOutResponse) bizResponse.getResult();
        ConvertUtil.convertInput(userLogInOutResponse);
    }

    /**
     * 更新用户登录错误次数
     *
     * @param userInfo 用户信息
     * @throws Exception 异常
     */
    private void updateUserLoginErrorTimes(UserInfo userInfo) throws Exception {
        BspsUserInfoMapper bspsUserInfoMapper = new BspsUserInfoMapperImpl();
        if (null == userInfo.getLastLoginDate() || !userInfo.getLastLoginDate().equals(DateUtil.getCurrentDate())) {
            userInfo.setLastLoginDate(DateUtil.getCurrentDate());
            userInfo.setLoginErrorTimes(1);
        } else {
            int loginErrorTimes = userInfo.getLoginErrorTimes() + 1;
            userInfo.setLoginErrorTimes(loginErrorTimes);
        }
        /* 更新登录错误信息 */
        int iReturnCode = bspsUserInfoMapper.updateBspsUserErrorTimeByPrimaryKey(userInfo);
        if (0 != iReturnCode) {
            rglog.error("更新用户登录次数失败信息失败!");
        }
    }

    /**
     * 登记用户登录登出信息
     *
     * @param userLogInOutRequest 用户请求参数
     * @throws Exception 异常
     */
    private void registerUserLoginInfo(UserLogInOutRequest userLogInOutRequest, String userId, UserInfo userInfo, String sessionId) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        UserLoginInfo userLoginInfo = new UserLoginInfo();
        BspsUserLoginInfoMapper bspsUserLoginInfoMapper = new BspsUserLoginInfoMapperImpl();
        userLoginInfo.setInstId(userLogInOutRequest.getHeader().getInstId());
        userLoginInfo.setLoginType(userLogInOutRequest.getHeader().getChanlId());
        userLoginInfo.setUserId(userId);
        userLoginInfo.setLoginTime(DateUtil.getCurrentDateTime(BspsAppParamConstant.yyyy_MM_dd_HHmmssSSS));
        userLoginInfo.setSessionId(sessionId);
        userLoginInfo.setLastOprTime(DateUtil.getCurrentDateTime(BspsAppParamConstant.yyyy_MM_dd_HHmmssSSS));
        userLoginInfo.setLoginStatus("0");   //0-登录  1-登出

        userLoginInfo.setLoginIp(userLogInOutRequest.getDevRiskInfo().getDevIp());
        userLoginInfo.setDevModel(userLogInOutRequest.getDevRiskInfo().getDevModel());
        userLoginInfo.setDevSn(userLogInOutRequest.getDevRiskInfo().getDevSerialNo());
        userLoginInfo.setDevUnqId(userLogInOutRequest.getDevRiskInfo().getDevUniqueId());
        userLoginInfo.setDevMac(userLogInOutRequest.getDevRiskInfo().getDevMac());
        userLoginInfo.setLoginLongitude(userLogInOutRequest.getDevRiskInfo().getLongitude());
        userLoginInfo.setLoginLatitude(userLogInOutRequest.getDevRiskInfo().getLatitude());
        userLoginInfo.setAppVersion(userLogInOutRequest.getHeader().getVersion());
        /* 开启数据库事务 */
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.OLTP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.OLTP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();

        int iReturnCode = bspsUserLoginInfoMapper.insertBspsUserLoginInfo(userLoginInfo);
        if (0 != iReturnCode) {
            dbsUtil.dbsEndTransaction(false);
            rglog.error("登记用户登录信息表失败,iReturnCode:<{}>", iReturnCode);
            throw new BizException(RespCodeEnum.REGISTER_USER_LOGIN_INFO_ERROR.getRespCode(), RespCodeEnum.REGISTER_USER_LOGIN_INFO_ERROR.getRespDesc());
        }

        /* 更新openID */
        if (!StringUtils.isEmpty(userLogInOutRequest.getOpenId()) && "WECHAT".equals(userLogInOutRequest.getHeader().getChanlId())) {
            BspsUserInfoMapper bspsUserInfoMapper = new BspsUserInfoMapperImpl();
            iReturnCode = bspsUserInfoMapper.updateBspsOpenIdByPrimaryKey(userInfo, userLogInOutRequest.getOpenId());
            if (0 != iReturnCode) {
                dbsUtil.dbsEndTransaction(false);
                rglog.error("登记用户登录信息表失败,iReturnCode:<{}>", iReturnCode);
                throw new BizException(RespCodeEnum.UPDATE_USER_INFO_ERROR.getRespCode(), RespCodeEnum.UPDATE_USER_INFO_ERROR.getRespDesc());
            }
        }

        dbsUtil.dbsEndTransaction(true);

    }


    /**
     * 更新用户登录登出信息
     *
     * @param userLogInOutRequest 用户请求参数
     * @throws Exception 异常
     */
    private void updateUserLoginInfoByLogout(UserLogInOutRequest userLogInOutRequest) throws Exception {

        UserLoginInfo userLoginInfo = new UserLoginInfo();
        BspsUserLoginInfoMapper bspsUserLoginInfoMapper = new BspsUserLoginInfoMapperImpl();
        userLoginInfo.setInstId(userLogInOutRequest.getHeader().getInstId());
        userLoginInfo.setSessionId(userLogInOutRequest.getHeader().getSession());
        userLoginInfo.setUserId(userLogInOutRequest.getUserId());
        userLoginInfo.setLastOprTime(DateUtil.getCurrentDateTime(BspsAppParamConstant.yyyy_MM_dd_HHmmssSSS));
        userLoginInfo.setLoginStatus("1");

        userLoginInfo.setLoginIp(userLogInOutRequest.getDevRiskInfo().getDevIp());
        userLoginInfo.setDevModel(userLogInOutRequest.getDevRiskInfo().getDevModel());
        userLoginInfo.setDevSn(userLogInOutRequest.getDevRiskInfo().getDevSerialNo());
        userLoginInfo.setDevUnqId(userLogInOutRequest.getDevRiskInfo().getDevUniqueId());
        userLoginInfo.setDevMac(userLogInOutRequest.getDevRiskInfo().getDevMac());
        userLoginInfo.setLoginLongitude(userLogInOutRequest.getDevRiskInfo().getLongitude());
        userLoginInfo.setLoginLatitude(userLogInOutRequest.getDevRiskInfo().getLatitude());
        userLoginInfo.setAppVersion(userLogInOutRequest.getHeader().getVersion());
        int iReturnCode = bspsUserLoginInfoMapper.updateBspsUserLoginInfoByUserIdAndSessionId(userLoginInfo);
        if (0 != iReturnCode) {
            rglog.error("登记用户登录信息表失败,iReturnCode:<{}>", iReturnCode);
            throw new BizException(RespCodeEnum.REGISTER_USER_LOGIN_INFO_ERROR.getRespCode(), RespCodeEnum.REGISTER_USER_LOGIN_INFO_ERROR.getRespDesc());
        }
    }
}
